package com.lanhai.zhonglai.impl;

import java.util.ArrayList; 
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.lanhai.zhonglai.MsgCore;
import com.lanhai.zhonglai.beans.AgvBean; 
import com.lanhai.zhonglai.beans.ControlAreaLockBean;
import com.lanhai.zhonglai.dao.ControlAreaDao;
import com.lanhai.zhonglai.dao.RelDotAreaDao;
import com.lanhai.zhonglai.interfaces.IAgv;
import com.lanhai.zhonglai.interfaces.IAgvEvent;
import com.lanhai.zhonglai.interfaces.IControlArea;
import com.lanhai.zhonglai.mapper.ControlAreaMapper; 
import com.lanhai.zhonglai.utils.Tools;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * 交管区域
 * @author zhengwei
 *
 */
@Service 
public class ControlAreaImpl implements IControlArea{

	@Autowired
	ControlAreaMapper caMapper;
	
	@Autowired
	JedisPool jedisPool;
	
	@Autowired
	IAgvEvent iAgvEvent;
	
	@Autowired
	IAgv iAgv;
	
	//所有的缓存区域（只读)
	static  List<ControlAreaDao> list=  new ArrayList<ControlAreaDao>();
	
	//锁定的区域
	static Map<Long, ControlAreaLockBean> lockMap=  new ConcurrentHashMap<Long,ControlAreaLockBean>();
 
	static List<RelDotAreaDao> dotList= new ArrayList<RelDotAreaDao>();
	
	
 
	/**
	 * 是否到达某区域 
	 */
	@Override
	public long getAreaId(int x, int y) { 
		long p=0;
		for (ControlAreaDao dao : list) {
			if(dao.getMinx()<=x && x<= dao.getMaxx() && dao.getMiny()<=y && y<=dao.getMaxy()) {
				p=dao.getId();
				break;
			}
		}
		return p;
	}
	
	

	/**
	 *锁定区域
	 */
	@Override
	public synchronized  boolean lockArea(long areaId, int agvid) {  
		ControlAreaLockBean bean=getBean(areaId);
		if(bean.isLocking()&&bean.getAgvid()==agvid) {
			 return true;	
		 
		}
		if(bean.isLocking()==false) {
			bean.setLocking(true); 
			bean.setAgvid(agvid);
			saveCache(bean);
			return true;
		} 
		return false;
	}

 

 
	/**
	 * 
	 * 区域解锁。如果这个区域还有其它小车
	 * areaId:当前交管区id
	 * agvid:调用的agvid
	 */
	@Override
	public synchronized void unlockArea(long areaId ) {   
		ControlAreaLockBean bean=getBean(areaId); 
		if(bean.getStopAgv()==null||bean.getStopAgv().size()==0) { 
			bean.setLocking(false);
			bean.setAgvid(0);
			saveCache(bean); 
			return;
		}
		//找到队列中第一辆车，并移除掉
		 int agvid=Tools.strToInt( bean.getStopAgv().get(0));
		 bean.getStopAgv().remove(0); 
		 bean.setAgvid(agvid); 
		 saveCache(bean); 
		  
		 //启动小车
		 AgvBean agv=iAgv.getBean(agvid);
		 if(agv!=null) {
			 if(agv.getAreaId()==areaId) {
				 //在同一个区域内  
				 iAgvEvent.stopOrstart(agv, false);
			 }else {
				 //目标小车已经离开，继续解锁
				 unlockArea(areaId);
			 } 
		 } else {
			 //小车不存在,继续下一辆车
			 unlockArea(areaId);
		 }
	}
 

	/**
	 *判断小车是否是某路段的上锁者
	 */
	@Override
	public boolean isLocker(long areaId, int agvid) {
		ControlAreaLockBean bean=getBean(areaId); 
		if(bean.isLocking()==false) return false;
		 return  bean.getAgvid()==agvid;
	 
	}

 

	/**
	 *添加交管的小车
	 */
	@Override
	public synchronized boolean addStopAgv(long areaId, int agvid) {
		ControlAreaLockBean bean=getBean(areaId); 
		String ak=""+agvid;  
		//交管被锁+锁的车不是当前小车+列表中没有当前小车
		if(bean.isLocking()&&bean.getAgvid()!=agvid&& bean.getStopAgv().contains(ak)==false  ) {
			bean.getStopAgv().add(ak);
			saveCache(bean);
			return true;
		}else {
			return false;
		}
		
		
	}

	 
	/**
	 * 从redis中拿数据
	 */
	 
	 synchronized ControlAreaLockBean getBean(long areaId) {
		ControlAreaLockBean bean=lockMap.get(areaId);
		if (bean == null) {
			String mainkey = "controlarea";
			String key = String.format("%d", areaId);
			Gson gson = new Gson();
			Jedis jd = jedisPool.getResource();
			String json = jd.hget(mainkey, key);
			if (json != null && json.isEmpty() == false) {
				try {
					bean = gson.fromJson(json, ControlAreaLockBean.class);
				} catch (Exception e) {

				}
			}
			if (bean == null) { 
				for (ControlAreaDao dao : list) {
					if (dao.getId() == areaId) {
						bean = new ControlAreaLockBean();
						bean.setAreaid(dao.getId());
						bean.setAgvid(0);
						bean.setLocking(false);
						json = gson.toJson(bean);
						jd.hset(mainkey, key, json);

						lockMap.put(areaId, bean);
						break;
					}
				}
			}
			jd.close();
		}
		return bean;
	}

	 

	//保存 
	 synchronized void saveCache(ControlAreaLockBean bean) {
		 
			lockMap.put(bean.getAreaid(), bean);
			
			String mainkey = "controlarea";
			String key = String.format("%d", bean.getAreaid()); 
			Gson gson=new Gson();
			String json=gson.toJson(bean);
			Jedis jd=jedisPool.getResource(); 
			jd.hset(mainkey, key,json);
			jd.close();
		 
	}

	@Override
	public void init() { 
		List<ControlAreaDao> tmp = caMapper.getAreaAll();
		if (tmp != null && tmp.size() > 0) {
			list.clear();
			list.addAll(tmp);
			  
		}
		List<RelDotAreaDao> rtmp = caMapper.getRelList();
		dotList.clear();
		if (rtmp != null) {
			dotList.addAll(rtmp);
		}
	}
 

	
	/**
	 *移除指定区域内的小车
	 */
	@Override
	public synchronized void removeStopAgv(long areaId, int agvid) {

		ControlAreaLockBean bean = getBean(areaId);
		if (bean == null)
			return;

		if (bean.getAgvid() != agvid) {
			// 不是当前小车锁定的
			if (bean.getStopAgv() != null && bean.getStopAgv().contains("" + agvid)) {
				bean.getStopAgv().remove("" + agvid);
				saveCache(bean);
				return;
			}
		} else {
			// 是当前小车锁定的
			if (bean.getStopAgv() == null || bean.getStopAgv().size() == 0) {
				// 没有其它车
				bean.setAgvid(0);
				bean.setLocking(false);
				saveCache(bean);
			} else {
				// 拿出第一辆车
				int firstagvid = Tools.strToInt(bean.getStopAgv().get(0));
				bean.getStopAgv().remove(0);
				bean.setAgvid(firstagvid);
				bean.setLocking(true);
				saveCache(bean);

				// 启动小车
				AgvBean agv = iAgv.getBean(firstagvid);

				if (agv != null) {
					if (agv.getAreaId() == bean.getAreaid()) {
						// 在同一个区域内
						MsgCore.sendMsg(agv.getAgvId(), "交管允许前进");
						iAgvEvent.stopOrstart(agv, false);
					}
				}
			}

		}
	}



	@Override
	public boolean isLockedForDot( int dotno,int agvid) {
		long areaid=0;
		for(RelDotAreaDao dao : dotList) {
			if(dao.getDotno()==dotno) {
				areaid=dao.getAreaid();
				break;
			}
		}
		if(areaid==0) {
			return false;
		}
		ControlAreaLockBean bean = getBean(areaid);
		if(bean==null) return false;
		if(bean.isLocking()==false) return false;
		if(bean.isLocking() ==true&&bean.getAgvid()==agvid) return false;
		return true;
	}



	@Override
	public boolean areaIsLocked(int areaid, int agvid) {
		if(areaid==0) return false;
		
		
		ControlAreaLockBean bean = getBean(areaid);
		if(bean==null) return false;
		if(bean.isLocking()==false) return false;
		if(bean.isLocking() ==true&&bean.getAgvid()==agvid) return false;
		return true;
	}

 
}
